package com.niepan.modules.zhinenganjianback.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.niepan.common.utils.MD5Util;
import com.niepan.common.utils.PinyinUtils;
import com.niepan.common.utils.R.ApiResponse;
import com.niepan.common.utils.R.Result;
import com.niepan.common.utils.SplitDateUtils;
import com.niepan.modules.zhinenganjianback.VO.DataVo;
import com.niepan.modules.zhinenganjianback.VO.LargeScreenDataVo;
import com.niepan.modules.zhinenganjianback.common.EM_INSIDE_OBJECT_TYPE;
import com.niepan.modules.zhinenganjianback.dao.LargeScreenDao;

import com.niepan.modules.zhinenganjianback.dto.AreaCount;
import com.niepan.modules.zhinenganjianback.dto.AreaDwscode;
import com.niepan.modules.zhinenganjianback.dto.AreaMap;
import com.niepan.modules.zhinenganjianback.service.AreaCountService;
import com.niepan.modules.zhinenganjianback.service.AreaDwscodeService;
import com.niepan.modules.zhinenganjianback.service.AreaMapService;
import com.niepan.modules.zhinenganjianback.service.LargeScreenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: liuchenyu
 * @date: 2023/3/27
 */
@Service
public class LargeScreenServiceImpl implements LargeScreenService {

    @Autowired
    private LargeScreenDao largeScreenDao;
    @Autowired
    private AreaMapService areaMapService;
    @Autowired
    private PinyinUtils pinyinUtils;

    @Autowired
    private AreaDwscodeService areaDwscodeService;
    @Autowired
    private AreaCountService areaCountService;

    @Override
    public List<Map<String, Object>> getCount() {
        List<Map<String, Object>> res = new ArrayList<>();
        List<Map<String, Object>> areaList = largeScreenDao.getArea();
        for (Map<String, Object> area : areaList) {
            String province = (String) area.get("province");
            Map<String,Object> map = largeScreenDao.getCountByArea(province);
            map.put("name",province);
            res.add(map);
        }
        //去重
        List<Map<String, Object>> collect = res.stream().distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<Map<String, Object>> getCountByProvince(String areaName) {
        List<Map<String, Object>> res = new ArrayList<>();
        List<Map<String, Object>> areaList = largeScreenDao.getAreaByName(areaName);
        for (Map<String, Object> area : areaList) {
            String city = (String) area.get("city");
            Map<String,Object> map = largeScreenDao.getCountByCity(city);
            map.put("name",city);
            res.add(map);
        }
        //去重
        List<Map<String, Object>> collect = res.stream().distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<Map<String, Object>> getCountByCity(String areaName) {
        List<Map<String, Object>> res = new ArrayList<>();
        List<Map<String, Object>> areaList = largeScreenDao.getAreaByCity(areaName);
        for (Map<String, Object> area : areaList) {
            String centre = (String) area.get("centre");
            Map<String,Object> map = largeScreenDao.getCountByCentre(centre);
            String name = centre.substring(0, centre.indexOf("集"));
            map.put("name",name);
            res.add(map);
        }
        //去重
        List<Map<String, Object>> collect = res.stream().distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<Map<String, Object>> getDangerCountByTime(String machineGrade, String machineBrand, String startTime, String endTime) {
        List<Map<String, Object>> res = largeScreenDao.getDangerCountByTime(machineGrade,machineBrand,startTime,endTime);
        for (Map<String, Object> re : res) {
            String centre = (String) re.get("centre");
            String substring = centre.substring(0, centre.indexOf("集") - 1);
            re.put("name",substring);
        }
        return res;
    }

    /*@Override
    public List<Map<String, Object>> getDangerRank(String machineGrade, String machineBrand, String startTime, String endTime,String areaName) {
        List<Map<String, Object>> res = largeScreenDao.getDangerRank(machineGrade,machineBrand,startTime,endTime,areaName);
        Integer count = largeScreenDao.getCount(startTime,endTime,areaName);
        for (Map<String, Object> re : res) {
            Integer type = (Integer) re.get("type");
            Long value = (Long)re.get("value");
            Long Proportion = value * 100 / count;
            String noteByValue = EM_INSIDE_OBJECT_TYPE.getNoteByValue(type);
            re.put("name",noteByValue);
            re.put("Proportion",Proportion);
        }
        List<Map<String, Object>> result = res.stream().sorted((e1, e2) -> {
            // 升序
            // return Long.compare((Long) e1.get("value"), (Long) e2.get("value"));
            // 降序
            return -Long.compare((Long) e1.get("value"), (Long) e2.get("value"));
        }).collect(Collectors.toList());
        return result;
    }*/

    @Override
    public List<String[]> getDangerRank(String machineGrade, String machineBrand, String startTime, String endTime,String areaName) {
        List<Map<String, Object>> res = largeScreenDao.getDangerRank(machineGrade,machineBrand,startTime,endTime,areaName);
        Integer count = largeScreenDao.getCount(startTime,endTime,areaName);
        String lastDayStartTime = getPreDateByDate(startTime);
        String lastDayEndTime = getPreDateByDate(endTime);

        List<Map<String, Object>> lastDayRes = largeScreenDao.getDangerRank(machineGrade,machineBrand,lastDayStartTime,lastDayEndTime,areaName);
        Integer lastDayCount = largeScreenDao.getCount(lastDayStartTime,lastDayEndTime,areaName);
        List<String[]> result = new ArrayList<>();
        for (int i = 0; i < res.size(); i++) {
            String[] str = new String[4];
            List<String> list = new ArrayList<>();
            Integer type = (Integer) res.get(i).get("type");
            Long value = (Long)res.get(i).get("value");
            Long Proportion = value * 100 / count;
            String noteByValue = EM_INSIDE_OBJECT_TYPE.getNoteByValue(type);
            res.get(i).put("name",noteByValue);
            res.get(i).put("Proportion",Proportion);

            list.add(value.toString());
            list.add(noteByValue);
            list.add(Proportion.toString());

            str[0] = noteByValue;//名字
            str[1] = value.toString();//数量
            str[2] = Proportion.toString();//百分比
            str[3] = "1";

            if (lastDayRes.size() == 0){
                str[3] = "1";
            } else {
                for (int j = 0; j < lastDayRes.size(); j++) {
                    if (res.get(i).get("type") == lastDayRes.get(j).get("type")){
                        Long value1 = (Long)lastDayRes.get(j).get("value");
                        String noteByValue1 = EM_INSIDE_OBJECT_TYPE.getNoteByValue(type);
                        Long Proportion1 = value1 * 100 / lastDayCount;

                        if (Proportion > Proportion1){
                            str[3] = "1";//上升
                        } else if (Proportion < Proportion1){
                            str[3] = "2";//下降
                        } else {
                            str[3] = "0";//持平
                        }
                    }
                }
            }
            result.add(str);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getTotal() {
        List<Map<String, Object>> res = largeScreenDao.getTotal();
        return res;
    }

    @Override
    public List<Map<String, Object>> getCountStatistics(String areaName, String machineGrade, String machineBrand, String startTime, String endTime) {
        //使用工具类，传入两个时间范围，返回这两个时间范围内的所有日期，并保存在一个集合中
        List<String> everyDay = SplitDateUtils.findEveryDay(startTime, endTime);
        List<Map<String, Object>> res = new ArrayList<>();
        for (String day : everyDay) {
            Map<String, Object> map = new HashMap<>();
            List<Map<String, Object>> list = new ArrayList<>();
            EM_INSIDE_OBJECT_TYPE[] values = EM_INSIDE_OBJECT_TYPE.values();
            for (EM_INSIDE_OBJECT_TYPE value : values) {
                Map<String, Object> countByType = largeScreenDao.getCountByType(areaName, machineGrade, machineBrand, day, value.getValue());
                countByType.put("type",value.getNote());
                list.add(countByType);
            }
            map.put("area",areaName);
            map.put("day",day);
            map.put("data",list);
            res.add(map);
        }
        return res;
    }

    @Override
    public Integer getTodayCount(String areaName) {
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date(System.currentTimeMillis());
        String format = formatter.format(date);
        Integer res = largeScreenDao.getTodayCount(areaName,format);
        return res;
    }

    @Override
    public Integer getDangerCount(String areaName) {
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date(System.currentTimeMillis());
        String format = formatter.format(date);
        Integer res = largeScreenDao.getDangerCount(areaName,format);
        return res;
    }

    @Override
    public List<Map<String, Object>> getDangerByType(String areaName) {
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date(System.currentTimeMillis());
        String format = formatter.format(date);
        List<Map<String, Object>> res = largeScreenDao.getDangerByType(areaName,format);
        Integer count = largeScreenDao.getTodayDangerCount(areaName,format);
        List result = new ArrayList<>();
        for (Map<String, Object> re : res) {
            Map<String,Object> map = new HashMap<>();
            Integer type = (Integer) re.get("type");
            Long value = (Long)re.get("value");
            Long Proportion = value * 100 / count;
            String noteByValue = EM_INSIDE_OBJECT_TYPE.getNoteByValue(type);

            map.put("type",type);
            map.put("name",noteByValue);
            map.put("value",value);
            map.put("Proportion",Proportion);
            result.add(map);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getTotalByCentre(String areaName, String startTime, String endTime) {
        List<Map<String, Object>> resTotal = largeScreenDao.getTotalByCentre(areaName,startTime,endTime);
        List<Map<String, Object>> resDanger = largeScreenDao.getFirstTotalByCentre(areaName,startTime,endTime);
        for (int i = 0; i < resTotal.size(); i++) {
            resTotal.get(i).put("resDanger",resDanger.get(i).get("value"));
        }
        return resTotal;
    }

    @Override
    public Integer getAllCount(String areaName, String startTime, String endTime) {
        Integer res = largeScreenDao.getAllCount(areaName,startTime,endTime);
        return res;
    }

    @Override
    public Integer DangerCount(String areaName, String startTime, String endTime) {
        Integer res = largeScreenDao.DangerCount(areaName,startTime,endTime);
        return res;
    }

    @Override
    public List<Map<String, Object>> getDangerArea(String startTime, String endTime,String areaName) {
        List<Map<String, Object>> res = largeScreenDao.getDangerArea(startTime,endTime,areaName);
        for (Map<String, Object> re : res) {
            String centre = (String) re.get("centre");
            String substring = centre.substring(0, centre.indexOf("集"));
            re.put("centre",substring);
        }
        return res;
    }

    @Override
    public Map<String, Object> getTotalDangerCount(String machineGrade, String machineBrand) {
        Map<String,Object> res = new HashMap<>();
        //获取今日日期
        String today = this.getToday();
        //获取前一日日期
        String beforeDay = this.getBefore(today, 1);
        //获取前一周日期
        String beforeWeek = this.getBefore(today, 7);
        //获取前一月日期
        String beforeMonth = this.getBefore(today, 30);

        List<Map<String, Object>> dangerCountByDay = this.getDangerCountByTime(machineGrade, machineBrand,beforeDay,today);
        List<Map<String, Object>> dangerCountByWeek = this.getDangerCountByTime(machineGrade, machineBrand,beforeWeek,today);
        List<Map<String, Object>> dangerCountByMonth = this.getDangerCountByTime(machineGrade, machineBrand,beforeMonth,today);
        res.put("dangerCountByDay",dangerCountByDay);
        res.put("dangerCountByWeek",dangerCountByWeek);
        res.put("dangerCountByMonth",dangerCountByMonth);
        return res;
    }

    @Override
    public Map<String,Object> totalCount(String areaName) {
        Map<String,Object> res = new HashMap<>();
        //获取今日日期
        String today = this.getToday();
        //获取前一日日期
        String beforeDay = this.getBefore(today, 1);
        //获取前一周日期
        String beforeWeek = this.getBefore(today, 7);
        //获取前一月日期
        String beforeMonth = this.getBefore(today, 30);

        Integer allCountDay = this.getAllCount(areaName, beforeDay, today);
        Integer allCountWeek = this.getAllCount(areaName, beforeWeek, today);
        Integer allCountMonth = this.getAllCount(areaName, beforeMonth, today);

        Integer dangerDay = this.DangerCount(areaName, beforeDay, today);
        Integer dangerWeek = this.DangerCount(areaName, beforeWeek, today);
        Integer dangerMonth = this.DangerCount(areaName, beforeMonth, today);
        res.put("allCountDay",allCountDay);
        res.put("allCountWeek",allCountWeek);
        res.put("allCountMonth",allCountMonth);
        res.put("dangerDay",dangerDay);
        res.put("dangerWeek",dangerWeek);
        res.put("dangerMonth",dangerMonth);
        return res;
    }

    @Override
    public Map<String, Object> todayCount(String areaName) {
        Map<String,Object> res = new HashMap<>();
        Integer TodayCount = this.getTodayCount(areaName);
        Integer DangerCount = this.getDangerCount(areaName);
        res.put("TodayCount",TodayCount);
        res.put("DangerCount",DangerCount);
        return res;
    }
    public String getToday(){
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String today = sf.format(date);
        return today;
    }

    /**
     * @Author：
     * @Description：获取当前日期的指定前几天
     * @Date：
     * @strData：参数格式：yyyy-MM-dd
     * @return：返回格式：yyyy-MM-dd
     */
    public String getPreDateByDate(String strData) {
        String preDate = "";
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(strData);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }

        c.setTime(date);
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 - 1);
        preDate = sdf.format(c.getTime());
        return preDate;
    }

    /**
     * @Author：
     * @Description：更加输入日期，获取输入日期的前一天
     * @Date：
     * @strData：参数格式：yyyy-MM-dd
     * @return：返回格式：yyyy-MM-dd
     */
    public String getBefore(String strData,Integer before) {
        String preDate = "";
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = sdf.parse(strData);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }

        c.setTime(date);
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 - before);
        preDate = sdf.format(c.getTime());
        return preDate;
    }

    @Override
    public ApiResponse receiveInfo(LargeScreenDataVo largeScreenDataVo) {
        DataVo data = largeScreenDataVo.getData();
        String jsonObject = JSON.toJSONString(data, SerializerFeature.SortField);
        System.out.println(jsonObject + "niepan2018.");
        String data_digest = MD5Util.getMD5(jsonObject + "niepan2018.");
        if (largeScreenDataVo.getData_digest().equals(data_digest)) {
            //进行数据存储
            //1通过areaCode和dwsCode查询数据库中是否存在该地区
            QueryWrapper<AreaMap> queryWrapper = new QueryWrapper<AreaMap>();
            queryWrapper.eq("area_code", data.getAreaCode());
            // queryWrapper.eq("dws_code",data.getDwsCode());
            AreaMap one = areaMapService.getOne(queryWrapper);
            if (one == null) {
                return Result.error("该地区不存在");
            }
            //设置时间

            String parseTime = parseTime(String.valueOf(data.getScanTime()));
            // data.setScanTime(parseTime(data.getScanTime()));
            //创建地区表对象
            AreaDwscode areaDwscode = new AreaDwscode();
            //todo 根据one
            areaDwscode.setDwsCode(data.getDwsCode());
            // todo 修改 按照areacode进行匹配地域信息
            areaDwscode.setChannel(one.getChannle());
            areaDwscode.setProvince(one.getProvince());
            areaDwscode.setCity(one.getCity());
            areaDwscode.setCentre(one.getCentre());
            //todo 后期需要修改为one.getAreaCode()获取
            //areaDwscode.setAreaCode(one.getAreaCode());
            areaDwscode.setAreaCode(data.getAreaCode());
            areaDwscode.setCounty(one.getCounty());
            areaDwscode.setSort(one.getSort());
            //1，查询数据库中是否存在在动态称编码
            //todo 根据one
            String dwscode = areaDwscodeService.selectByDwsCode(data.getDwsCode());
            //获取城市拼音
            String s = pinyinUtils.convertToPinyin(areaDwscode.getCity());
            String city = s.replaceAll("\\d", "");
            String contrabandName = city + "_danger_picture_info";
            //String normalName = province + "_normal_picture_info";
            String normalName = city + "_picture_info";
            if (!org.apache.commons.lang.StringUtils.isNotBlank(dwscode)) {   //如果不存在则直接存到对应的表中
                int contraband = largeScreenDao.checkTableExists("niepan", contrabandName);
                int normal = largeScreenDao.checkTableExists("niepan", normalName);
                if (contraband == 0 && normal == 0) {
                    largeScreenDao.useDatabase("niepan");
                    largeScreenDao.createContrabandTable(contrabandName);
                    largeScreenDao.createNormalTable(normalName);
                }
                areaDwscode.setDangerTableName(contrabandName);
                areaDwscode.setTableName(normalName);
                areaDwscodeService.save(areaDwscode); //保存地区表
            }
            String today = getTodayNoHHMMSS();//获取日期
            AreaCount areaCount = new AreaCount();
            String dayAndAreaCode = dayAndAreaCode(areaCount, areaDwscode, today);
            //判断是否为违禁品
            boolean isForbid = data.getIsForbid();
            if (isForbid) {
                String[] split = data.getForbidType().split(",");
                for (String s1 : split) {
                    data.setForbidType(s1);
                    int i = largeScreenDao.saveDangerInfo(contrabandName, data, parseTime);
                }
                //违禁品加一
                if (!org.apache.commons.lang.StringUtils.isNotBlank(dayAndAreaCode)) {
                    int i1 = areaCountService.updateDangerCount(areaCount.getId());
                } else {
                    int i1 = areaCountService.updateDangerCount(Integer.valueOf(dayAndAreaCode));
                }
            } else {
                int i = largeScreenDao.saveNormalInfo(normalName, data,parseTime);
                //非违禁品加一
                if (!org.apache.commons.lang.StringUtils.isNotBlank(dayAndAreaCode)) {
                    int i1 = areaCountService.updateNoDangerCount(areaCount.getId());
                } else {
                    int i1 = areaCountService.updateNoDangerCount(Integer.valueOf(dayAndAreaCode));
                }
            }
            return Result.success();
        }

        // todo 对i进行解析
        return Result.error("数据解析失败");

    }

    //获取当前时间 时分秒
    public String getTodayNoHHMMSS() {
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        String today = sf.format(date);
        return today;
    }

    //将时间戳转换成指定日期格式
    public String parseTime(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = sdf.format(new Date(Long.parseLong(time)));
        return format;
    }

    //获取查询当天的dwscode和日期是否存在
    @Override
    public String dayAndAreaCode(AreaCount areaCount, AreaDwscode areaDwscode, String today) {
        String dayAndAreaCode = areaCountService.dayAndAreaCode(areaDwscode.getAreaCode()); //查询当天的dwscode和日期是否存在
        if (!org.apache.commons.lang.StringUtils.isNotBlank(dayAndAreaCode)) { //如果不存在则更新
            //如果不存在则插入
            areaCount.setProvince(areaDwscode.getProvince());
            areaCount.setCity(areaDwscode.getCity());
            areaCount.setCentre(areaDwscode.getCentre());
            areaCount.setCounty(areaDwscode.getCounty());
            areaCount.setAreaCode(areaDwscode.getAreaCode());
            areaCount.setCreateTime(today);
            areaCount.setSort(areaDwscode.getSort());
            //4,插入数据库中。
            int i = areaCountService.insertData(areaCount);
            if (i == 0) {
//                log.error("插入失败");
            }
        }
        return dayAndAreaCode;
    }
}
